﻿/**
 * AbstractHibernateDao.java 1.0 2007-4-15 上午02:23:06,创建 by yangfan
 */


package org.in4j.core.dao;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.sql.SQLException;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.in4j.core.dao.support.Pagination;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.util.Assert;

/**
 *
 * @author 杨帆
 * @version 1.0 2007-4-15 上午02:23:06,创建
 */
public abstract class AbstractHibernateDao<T> extends HibernateDaoSupport implements BaseDao<T>
{
	private JdbcTemplate jdbcTemplate;

	private Class<T> entityClass;

	public AbstractHibernateDao()
	{
		this.entityClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
	}

	protected JdbcTemplate getJdbcTemplate()
	{
		return jdbcTemplate;
	}

	protected Class getEntityClass()
	{
		return entityClass;
	}

	public T load(Serializable id)
	{
		return (T)getHibernateTemplate().load(getEntityClass(), id);
	}

	public T getById(Serializable id)
	{
		return (T)this.getHibernateTemplate().get(getEntityClass(), id);
	}

	public void create(T entity)
	{
		this.getHibernateTemplate().save(entity);
	}

	public void update(T entity)
	{
		this.getHibernateTemplate().update(entity);
	}

	public void removeById(Serializable id)
	{
		this.getHibernateTemplate().delete(getById(id));
	}

	public void remove(T entity)
	{
		this.getHibernateTemplate().delete(entity);
	}

	public Query createQuery(String hql, Object... values)
	{
		Assert.hasText(hql);
		Query query = getSession().createQuery(hql);
		for(int i = 0; i < values.length; i++)
		{
			query.setParameter(i, values[i]);
		}
		return query;
	}

	public <ObjectType> ObjectType uniqueResult(String hql, Object... values)
	{
		Assert.hasText(hql);
		Query query = getSession().createQuery(hql);
		for(int i = 0; i < values.length; i++)
		{
			query.setParameter(i, values[i]);
		}
		return (ObjectType)query.uniqueResult();
	}

	public List<T> find(String hql, Object... values)
	{
		return this.getHibernateTemplate().find(hql, values);
	}

	public DetachedCriteria createDetachedCriteria()
	{
		return DetachedCriteria.forClass(getEntityClass());
	}

	public Pagination<T> findPageByCriteria(final DetachedCriteria detachedCriteria)
	{
		return findPageByCriteria(detachedCriteria, Pagination.PAGE_NO_FIRST);
	}

	public Pagination<T> findPageByCriteria(final DetachedCriteria detachedCriteria, final int pageNo)
	{
		return findPageByCriteria(detachedCriteria, pageNo, Pagination.PAGESIZE);
	}

	public Pagination<T> findPageByCriteria(final DetachedCriteria detachedCriteria, final int pageNo, final int pageSize)
	{
		final Pagination<T> result = (Pagination<T>)getHibernateTemplate().execute(new HibernateCallback()
		{
			public Object doInHibernate(Session session) throws HibernateException, SQLException
			{
				final Criteria criteria = detachedCriteria.getExecutableCriteria(session);
				final int count = (Integer)(criteria.setProjection(Projections.rowCount()).uniqueResult());
				criteria.setProjection(null).setResultTransformer(CriteriaSpecification.ROOT_ENTITY);
				final Pagination<T> pagination = new Pagination<T>(null, count, pageNo, pageSize);
//				System.out.println("startIndex--->" + pagination.getStartIndex());
				final List<T> items = criteria.setFirstResult(pagination.getStartIndex()).setMaxResults(pageSize).list();
				pagination.setItems(items);
				return pagination;
			}
		});
		return result;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate)
	{
		this.jdbcTemplate = jdbcTemplate;
	}
}
